#include "stdafx.h"

BEGIN_MESSAGE_MAP( CTestClientApp, CWinApp )
	ON_COMMAND( ID_HELP, &CWinApp::OnHelp )
END_MESSAGE_MAP( )

#if _DEBUG
class CStaticDebugInit {
public:
	CStaticDebugInit( ) {
		_CrtSetReportMode( _CRT_WARN,   _CRTDBG_MODE_DEBUG );
		_CrtSetReportMode( _CRT_ERROR,  _CRTDBG_MODE_DEBUG );
		_CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_DEBUG );

		_CrtSetDbgFlag( _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG ) | _CRTDBG_ALLOC_MEM_DF | _CRTDBG_CHECK_ALWAYS_DF | _CRTDBG_DELAY_FREE_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
	}
};
static CStaticDebugInit staticDebugInit;
#endif

class CTestClientModule:
	public ATL::CAtlMfcModule
{
public:
	DECLARE_LIBID( LIBID_TestClientLib );
	DECLARE_REGISTRY_APPID_RESOURCEID( IDR_TESTCLIENT, "{7C49C624-1EB4-490D-AD14-84320D73DF38}" );
};

CTestClientApp theApp;
CTestClientModule _AtlModule;

CTestClientApp::CTestClientApp( ) {
}

BOOL CTestClientApp::InitInstance( ) {
	AfxOleInit( );

	// Parse command line for standard shell commands, DDE, file open
	CCommandLineInfo cmdInfo;
	ParseCommandLine( cmdInfo );

	// Register class factories via CoRegisterClassObject( ).
	if ( FAILED( _AtlModule.RegisterClassObjects( CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE ) ) ) {
		return FALSE;
	}

	// InitCommonControlsEx() is required on Windows XP if an application
	// manifest specifies use of ComCtl32.dll version 6 or later to enable
	// visual styles.  Otherwise, any window creation will fail.
	INITCOMMONCONTROLSEX InitCtrls = { sizeof( InitCtrls ), ICC_WIN95_CLASSES };
	InitCommonControlsEx( &InitCtrls );

	CWinApp::InitInstance( );

	// Standard initialization
	// If you are not using these features and wish to reduce the size
	// of your final executable, you should remove from the following
	// the specific initialization routines you do not need
	// Change the registry key under which our settings are stored
	// TODO: You should modify this string to be something appropriate
	// such as the name of your company or organization
	SetRegistryKey( L"Zive Technology Research\\Panic Button" );

	// Construct all of the objects in the PanicButton stack, and do most of the setup.
	if ( !_CreatePanicButtonObjects( ) ) {
		return FALSE;
	}

	CTestClientDlg dlg( m_pPanicButton, m_pPanicButtonEventSink );
	m_pMainWnd = &dlg;
	
	// In an unusual twist, we don't care about the return value from dlg.DoModal().
	dlg.DoModal( );

	// Release the PanicButton objects.
	_ReleasePanicButtonObjects( );

	// Since the dialog has been closed, return FALSE so that we exit the
	//  application, rather than start the application's message pump.
	return FALSE;
}

BOOL CTestClientApp::ExitInstance( void ) {
	_AtlModule.RevokeClassObjects( );

	return CWinApp::ExitInstance( );
}

bool CTestClientApp::_CreatePanicButtonObjects( void ) {
	HRESULT hr;
	
	hr = m_pPanicButton.CoCreateInstance( L"Zive.PanicButton", nullptr, CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER | CLSCTX_LOCAL_SERVER );
	if ( FAILED( hr ) ) {
		BreakIfDebuggerPresent( );

		return false;
	}

	CComPtr<IConnectionPointContainer> pConnectionPointContainer;
	hr = m_pPanicButton->QueryInterface( &pConnectionPointContainer );
	if ( FAILED( hr ) ) {
		BreakIfDebuggerPresent( );

		m_pPanicButton.Release( );
		return false;
	}

	hr = pConnectionPointContainer->FindConnectionPoint( IID_DPanicButtonEvents, &m_pConnectionPoint );
	if ( FAILED( hr ) ) {
		BreakIfDebuggerPresent( );

		pConnectionPointContainer.Release( );
		m_pPanicButton.Release( );
		return false;
	}

	pConnectionPointContainer.Release( );

	hr = m_pPanicButtonEventSink.CoCreateInstance( CLSID_PanicButtonEventSink, nullptr, CLSCTX_LOCAL_SERVER );
	if ( FAILED( hr ) ) {
		BreakIfDebuggerPresent( );

		m_pConnectionPoint.Release( );
		m_pPanicButton.Release( );
		return false;
	}

	hr = m_pConnectionPoint->Advise( m_pPanicButtonEventSink, &m_dwConnectionPointCookie );
	if ( FAILED( hr ) ) {
		BreakIfDebuggerPresent( );

		m_pPanicButtonEventSink.Release( );
		m_pConnectionPoint.Release( );
		m_pPanicButton.Release( );
		return false;
	}

	return true;
}

void CTestClientApp::_ReleasePanicButtonObjects( void ) {
	HRESULT hr;

	hr = m_pConnectionPoint->Unadvise( m_dwConnectionPointCookie );
	if ( FAILED( hr ) ) {
		BreakIfDebuggerPresent( );
	}

	m_pPanicButtonEventSink.Release( );
	m_pConnectionPoint.Release( );
	m_pPanicButton.Release( );
}
